/* tslint:disable */
import { Action } from '@ngrx/store';
import { type } from '../util';
import { BaseLoopbackActionTypesFactory, BaseLoopbackActionsFactory } from './base';
import { LoopBackFilter, SDKToken, <%- modelName %> } from '../models';

export const <%- modelName %>ActionTypes =
Object.assign(BaseLoopbackActionTypesFactory('<%- modelName %>'), {
<% model.methods.forEach(function(action) {
  var methodName = action.name.split('.').join('$').replace('prototype$', '').replace(/::/g, '__');

  // all of these methods are extended from base service
  if (methodName.match(/(^create$|^createMany$|^find$|^replaceOrCreate$|^replaceById$|^upsert$|^upsertWithWhere$|^exists$|^findOne$|^findById$|^deleteById$|^updateAttributes$|^patchOrCreate$|^patchAttributes$|^updateAll$|^count$|^createChangeStream$)/)) { return; }

  // Unsupported and out of scope methods
  if (methodName.match(/(^exists$|^__exists|^myRemote$|^stats$|^count$|^__count)/)) { return; }

  if (!model.sharedClass.ctor.settings.sdk.blacklist[methodName]) {
-%>
  <%- upperCasedMethodName(methodName) %>: type('[<%- modelName %>] <%- normalizeMethodName(methodName) %>'),
  <%- upperCasedMethodName(methodName) %>_SUCCESS: type('[<%- modelName %>] <%- normalizeMethodName(methodName) %> success'),
  <%- upperCasedMethodName(methodName) %>_FAIL: type('[<%- modelName %>] <%- normalizeMethodName(methodName) %> fail'),

<% } -%>
<% }); // model.methods.foreach -%>
}<% if (model.isUser) { -%>, {

  /**
   * @author João Ribeiro <@JonnyBGod> <github:JonnyBGod>
   * @description
   * <%- modelName %> specific action types
   */
  SIGNUP: type('[<%- modelName %>] Signup'),
  SIGNUP_SUCCESS: type('[<%- modelName %>] Signup success'),
  SIGNUP_FAIL: type('[<%- modelName %>] Signup fail'),
}<% } -%>);

export const <%- modelName %>Actions =
Object.assign(BaseLoopbackActionsFactory<<%- modelName %>>(<%- modelName %>ActionTypes), {
<% model.methods.forEach(function(action) {
  var methodName = action.name.split('.').join('$').replace('prototype$', '').replace(/::/g, '__');
  var httpVerb = action.getEndpoints ? action.getEndpoints()[0].verb : action.getHttpMethod();
  var fullPath = action.getEndpoints ? action.getEndpoints()[0].fullPath : action.getFullPath();

  // all of these methods are extended from base service
  if (methodName.match(/(^create$|^createMany$|^find$|^replaceOrCreate$|^replaceById$|^upsert$|^upsertWithWhere$|^exists$|^findOne$|^findById$|^deleteById$|^updateAttributes$|^patchOrCreate$|^patchAttributes$|^updateAll$|^count$|^createChangeStream$)/)) { return; }

  // Unsupported and out of scope methods
  if (methodName.match(/(^exists$|^__exists|^myRemote$|^stats$|^count$|^__count)/)) { return; }

  if (!model.sharedClass.ctor.settings.sdk.blacklist[methodName]) {
  ngdocForAction(modelName, methodName, action, httpVerb, fullPath);
-%>
  <%- normalizeMethodName(methodName) %>: class implements Action {
    public readonly type = <%- modelName %>ActionTypes.<%- upperCasedMethodName(methodName) %>;
  <% if (action.accepts.filter(param => !paramIsContext(param) && !paramIsFunction(param)).length < 1) { -%>
    
    constructor(public meta?: any) {}
  <% } else if (action.accepts.filter(param => !paramIsContext(param) && !paramIsFunction(param)).length < 2) { -%>
    
    constructor(public payload: any, public meta?: any) {}
  <% } else { -%>
    public payload: {<%- buildPayloadParams(model, methodName, action.accepts) %>};

    constructor(<%- buildMethodParams(model, methodName, action.accepts) %>, public meta?: any) {
      this.payload = {<%- buildPayloadParamsWithoutTypes(model, methodName, action.accepts) %>};
    }
  <% } -%>
},
  <% ngdocForActionSuccess(modelName, methodName, action, httpVerb, fullPath); -%>
  <%- normalizeMethodName(methodName) %>Success: class implements Action {
    public readonly type = <%- modelName %>ActionTypes.<%- upperCasedMethodName(methodName) %>_SUCCESS;
  <% if (methodName.match(/(^__delete|^login$)/)) { -%>

    constructor(public payload: any, public meta?: any) {}
  <% } else if (methodName.match(/(^logout$)/)) { -%>

    constructor(public meta?: any) {}
  <% } else if (!action.returns || action.returns.length == 0) { -%>
    public payload: {id: any, fk: any};

    constructor(id: any, fk: any, public meta?: any) {
      this.payload = {id, fk};
    }
  <% } else { -%>
    public payload: {id: any, data: any};

    constructor(id: any, data: any, public meta?: any) {
      this.payload = {id, data};
    }
  <% } -%>
},
  /**
   * <%- normalizeMethodName(methodName) %>Fail Action.
   *
   * @param {any} payload
   * @param {any} meta (optional).
   * 
   */
  <%- normalizeMethodName(methodName) %>Fail: class implements Action {
    public readonly type = <%- modelName %>ActionTypes.<%- upperCasedMethodName(methodName) %>_FAIL;

    constructor(public payload: any, public meta?: any) { }
  },
<% } -%>
<% }); // model.methods.foreach -%>
}<% if (model.isUser) { -%>, {

  /**
   * <%- modelName %> specific actions
   */
  signup: class implements Action {
    public readonly type = <%- modelName %>ActionTypes.SIGNUP;

    constructor(public payload: any, public meta?: any) { }
  },

  signupSuccess: class implements Action {
    public readonly type = <%- modelName %>ActionTypes.SIGNUP_SUCCESS;
    public payload: {credentials: any, data: any};

    constructor(credentials: any, data: any, public meta?: any) {
      this.payload = {credentials, data};
    }
  },

  signupFail: class implements Action {
    public readonly type = <%- modelName %>ActionTypes.SIGNUP_FAIL;

    constructor(public payload: any, public meta?: any) { }
  },
}<% } -%>);
<%
function getJsDocType(arg) {
  return arg.type;
}

function ngdocForAction(modelName, methodName, action, httpVerb, fullPath) {
   // always add an empty line before the ngdoc comment:
-%>

  /**
   * <%- normalizeMethodName(methodName) %> Action.
<% if (action.deprecated) { -%>
   * @deprecated <%- action.deprecated %>
<% } -%>
<% if (!action.description) {
action.description =  '<em>\n' +
  '(The remote method definition does not provide any description.)\n' +
  '</em>';
} -%>
   * <%-: action.description | replace:/\n/g, '\n         * ' %>
<%
var params = action.accepts.filter(param => {
    return !paramIsContext(param);
});

var postData;
if (httpVerb == 'POST' || httpVerb == 'PUT' || httpVerb == 'PATCH') {
  params = params.filter(function(arg) {
    return arg.http && (arg.http.source == 'query' || arg.http.source == 'path');
  });
  postData = action.accepts.filter(function(arg) {
    return params.indexOf(arg) == -1 && !paramIsContext(arg) && !paramIsFunction(arg);
  });
}
-%>
   *
<% if (params.length != 0) {
  params.forEach(function(arg) { -%>
   * @param {<%- getJsDocType(arg) %>} <%- arg.arg %> <%-
(arg.description ? (Array.isArray(arg.description) ? arg.description.join('\n') : arg.description) : '').replace(/\n/g, '\n         *   ') %>
<%   if (model.isUser && methodName === 'login' && arg.arg === 'include') { -%>
   *   Default value: `user`.
<%   } -%>
<% }); } -%>
<% if (model.isUser && methodName === 'login') { -%>
   *  - `rememberMe` - `boolean` - Whether the authentication credentials
   *     should be remembered in localStorage across app/browser restarts.
   *     Default: `true`.
<% } -%>
<% if (postData) { -%>
   * @param {object} data Request data.
<% if (postData.length == 0) { -%>
   *
   * This method does not accept any data. Supply an empty object.
<% } else if (postData.length == 1 && postData[0].http &&
      postData[0].http.source == 'body' &&
      !postData[0].description) { -%>
   *
   * This method expects a subset of model properties as request parameters.
<% } else {
postData.forEach(function(arg) { -%>
   *
   *  - `<%- arg.arg %>` – `{<%- getJsDocType(arg)  %>}` - <%-
(arg.description ? (Array.isArray(arg.description) ? arg.description.join('\n') : arg.description) : '').replace(/\n/g, '\n         *   ') %>
<%   });
  }
} -%>
   * @param {any} meta (optional).
   * 
   */
<% } // end of ngdocForAction -%>
<%
function ngdocForActionSuccess(modelName, methodName, action, httpVerb, fullPath) {
   // always add an empty line before the ngdoc comment:
-%>
/**
<% if (action.deprecated) { -%>
   * @deprecated <%- action.deprecated %>
<% } -%>
   * <%- normalizeMethodName(methodName) %>Success Action.
   * 
<% var returnType = action.isReturningArray() ? 'object[]': 'object'; -%>
   * @param {any} id 
<% if (!action.returns || action.returns.length == 0) { -%>
   * This method returns no data.
<% } else if (action.returns[0].root) { -%>
<%   if (action.returns[0].description) { -%>
   * <%- action.returns[0].description
.replace(/\n/g, '\n   * ').trimRight() %>
<%   } else { -%>
   * @param {<%- returnType %>} data 
<%   } -%>
<% } else { -%>
   * Data properties:
<%   action.returns.forEach(function(arg) { -%>
   *
   *  - `<%- arg.arg %>` – `{<%- getJsDocType(arg)  %>}` - <%-
(arg.description ? (Array.isArray(arg.description) ? arg.description.join('\n') : arg.description) : '').replace(/\n/g, '\n         *   ') %>
<%   });
   }
-%>
   * @param {any} meta (optional).
   * 
   */
<% } // end of ngdocForActionSuccess -%>
